<?php

    if (!defined('__IS_LEAF__')) exit('Access Denied!');

    /**
     * 应用处理类
     * 检测应用（或分组）配置，生成应用（或分组），设置运行模式（app、group），根据不同运行模式调用路由器
     */

    class app {

        static private $appInfo=array();        //应用信息
        static private $groupInfo=array();      //应用信息
        static private $runMode;                //运行模式，分组或应用，即使app或group
        static private $instances;              //控制器实例化对象

        /**
         * 应用初始化
         * @access public
         */
        static public function init(){
            self::checkAppAndGroup();           //检测应用配置，应用有默认配置，如冲突，以用户级别优先
            self::buildApp();                   //生成项目
            //检测运行模式，应用模式或分组模式
            self::$runMode = defined('GROUP_NAME') ? 'group' : 'app';
        }

        /**
         * 检测应用配置是否正确，如正确，将解析后的结果放到$appInfo中
         * @access private
         */
        static private function checkAppAndGroup(){

            //如果不是分组机制
            if( !defined('GROUP_NAME') ){
                //获取应用名称及路径
                $app_name = defined('APP_NAME') ? APP_NAME : C('APP_NAME');
                if( !defined('APP_NAME') ) define('APP_NAME', $app_name);
                $app_path = defined('APP_PATH') ? APP_PATH : C('APP_PATH');
                //过滤用户可能在后面输入的/或\
                $app_path = rtrim( rtrim($app_path,'\\') ,'/' );
                /*
                 * 判断应用路径，如果为相对路径，则转换为绝对路径。如果为绝对路径，且存在，则使用该绝对路径
                 */
                //如果为绝对路径，且存在
                if( file_exists_case($app_path) ){
                    $app_path = $app_path.__SP__.$app_name;
                }
                //如果绝对路径不存在，或为相对路径
                else{
                    $app_path = realpath($app_path);
                    //设置安全防护，因为realpath后的$app_path如果为空，可能导致最后的$app_path为/home，当生成该目录的时候可能造成清空/home。
                    if( empty( $app_path ) ){
                        $app_path = __ROOT_DIR__.__SP__.$app_name;
                    }else{
                        $app_path = realpath($app_path).__SP__.$app_name;
                    }
                }
                //定义相关和应用相关的常量
                define('APP_ROOT', $app_path);
                define('DATA_PATH', APP_ROOT.__SP__.'data');
                define('LIBS_PATH', APP_ROOT.__SP__.'libs');
                define('CONTROLLER_PATH', LIBS_PATH.__SP__.'controller');
                define('SERVICE_PATH', LIBS_PATH.__SP__.'service');
                define('CACHE_PATH', APP_ROOT.__SP__.'data');
                define('TPL_PATH', APP_ROOT.__SP__.'tpl');
                define('LANG_PATH', APP_ROOT.__SP__.'lang');
                define('CONFIG_PATH', APP_ROOT.__SP__.'config');
                define('FUNCTION_PATH', APP_ROOT.__SP__.'function');
                //生成当前app_path（因为用户定义的app_path可能由相对路径转换为了绝对路径）和app_name(用户可能为定义app_name，而是系统采用默认的)
                C('app_path', $app_path);
                C('app_name', $app_name);
                self::$appInfo = array('app_name'=>$app_name, 'app_path'=>$app_path);
            }

        }

        /**
         * 根据配置，生成应用，遵循约定大于配置原则
         * @access private
         */
        static private function buildApp(){

            //待首次被创建的应用的默认目录和文件结构
            $buildArr = array(
                'function'=>'function.php',
                'libs/controller/'=>'indexController.php',
                'libs/service'=>'',
                'tpl/index/'=>'index.'.C('tpl_suffix'),
                'lang'=>'lang.Cn.ini',
                'data'=>'',
                'cache'=>'',
                'addons'=>'',
                'config'=>'config.php',
            );
            //创建目录和文件
            //如果应用目录存在，则略过，不再创建，以免由于覆盖造成整个项目丢失            
            if( !file_exists_case( APP_ROOT ) ){
                foreach ($buildArr as $buildKey => $buildValue) {
                    //目录
                    $dir = APP_ROOT.__SP__.$buildKey;
                    //创建文件，如果失败，抛出错误
                    !mkdir($dir, 0755, true) && trigger_error(L('build_dir_failure').'：'.$dir ,E_USER_ERROR);
                    //如果值$buildValue不为空，则创建文件
                    if(!empty($buildValue)){
                        $file = $dir.__SP__.$buildValue;
                        !touch($file) && trigger_error(L('build_file_failure').'：'.$file, E_USER_ERROR);
                        switch ($buildValue) {
                            case 'indexController.php':
                                $controllerTpl = __LEAF_DATA_DIR__.__SP__.'tpl'.__SP__.'controller.tpl';
                                file_put_contents($file, file_get_contents($controllerTpl));
                                break;
                            case 'config.php':
                                $configTpl = __LEAF_DATA_DIR__.__SP__.'tpl'.__SP__.'config.tpl';
                                file_put_contents($file, file_get_contents($configTpl));
                                break;
                            default:
                                # code...
                                break;
                        }
                    }
                }
            }

        }

        /**
         * 合并应用配置和系统配置
         */
        static private function mergeAppConfig(){

            //如果用户定义的配置文件不存在，则不进行合并操作
            $userConfigFile = CONFIG_PATH.__SP__.'config.php';
            if( !file_exists_case($userConfigFile) )  return false;
            //获取用户配置和系统配置
            $userConfig     = require $userConfigFile;
            core::$config = array_merge_recursive_distinct(core::$config, $userConfig);

        }

        /**
         * 返回运行模式
         * @access public
         */
        static public function getRunMode(){
 
            return self::$runMode;

        }

        /**
         * 运行app应用
         * 设置app相关信息，并运行app，路由器也是由此调用的
         * @access public
         */
        static public function appRun(){

            //合并配置操作，将用户配置与系统配置合并
            self::mergeAppConfig();
            //调用路由器，获取当前运行的控制器和方法（常量的方式）
            router::routeInit('app');
            $controller = APP_CONTROLLER;
            $method     = APP_METHOD;
            //实例化并运行app中的模块
            $model      = self::controllerInstance($controller);
            //if判断必不可少，因为当控制器不存在，$model有为false的时候
            if($model) $model->$method();
            
        }

        /**
         * 运行group分组
         * @access private
         */
        static private function groupRun(){
            Router::routeInit('groupRun');
        }

        /**
         * 实例化控制器
         * @access private
         * @param  $controller 控制器
         * @return object      返回实例化后的控制器对象
         */
        static private function controllerInstance($controller){

            if( empty($controller) ) return false;
            $controller .= 'Controller';
            $object = controller::getInstance($controller);
            //$object = new $controller;
            return $object;

        }

    }